using System;
using System.Configuration;
using System.Security;
using System.Text.RegularExpressions;
using System.Web.Services;
using System.Xml;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (Pty) ltd
	Author:		Alan Benington	
	Started:	2005-05-15	
	Status:		release	
	Version:	2.0.0
	Build:		20080120
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20070524:	Modification for .Net 2.0
	20070703:	Removed net_2_0 directive (from compatibility build)
	20071022:	Added AddImageBlog and AddImageBlogID methods
	20071121:	Added type string to base call on constructor 
				(add to other asmx.cs files also?)
	20080120:	Added Blog-Image methods (ie treats images like comments as
				a list connected to a blog)
	-----------------------------------------------------------------------	*/

namespace umlungu.engineX.blogX {
	/// <summary>
	/// umlungu EngineX.BlogX 
	/// This module is a component of the EngineX blogging and content management engine
	/// </summary>
	[WebService(Namespace="http://www.umlungu.com/engineX/")]
	public class adminX : x_result
	{
		/// <summary>
		/// Local objects to access internal methods
		/// </summary>
		#region Private methods
		x_recruit recruitx;
		x_user userx;
		x_blog blogx;
		x_blogspace blogspacex;
		#endregion

		#region Protected methods
		/// <summary>Constructor</summary>
		public adminX() : base("blogX") {	// set type
			try {
				userx = new x_user(Application);
				blogx = new x_blog(Application);
				blogspacex = new x_blogspace(Application);
				recruitx = new x_recruit(Application);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(SecurityException e) 	{_AddError(e);}
			catch(Exception e) 			{_AddError(e);}
		}
		#endregion

		#region General web service methods
		
		/// <summary>
		/// Logs a user on to the system
		/// </summary>
		/// <remarks>NB: this is the only method that is not validated</remarks>
		[WebMethod] public XmlDocument Login(string username, string password) {
			try {
				if (userx == null)
					throw new x_exception("error_user_null", "User object is null");
				userx.Login(username, password);
				string tok = userx.Token;
				XmlElement spacesel = (XmlElement) userx.User.SelectSingleNode("//blogspaces");
				XmlNodeList spaces = spacesel.SelectNodes("blogspace");
				foreach (XmlNode space in spaces) {
					XmlElement spaceel = (XmlElement) space;
					blogspacex.Get(spaceel.GetAttribute("name"));
					space.InnerText = blogspacex.Blogspace.SelectSingleNode("/blogspace/title").InnerText;
					XmlElement thisspaceel = (XmlElement) blogspacex.Blogspace.SelectSingleNode("/blogspace");
					spaceel.SetAttribute("type", (thisspaceel != null)? thisspaceel.GetAttribute("type") : "text");
					// Now get the blogs + authors for default
					if (spaceel.GetAttribute("name") == spacesel.GetAttribute("default")) {
						blogx.List(spaceel.GetAttribute("name"), "default");
						XmlNode usersnode = blogspacex.Blogspace.SelectSingleNode("//users");
						space.InnerXml = String.Concat(space.InnerXml,  blogx.Blogs.InnerXml, usersnode.OuterXml);
						spaceel.SetAttribute("topic", "default");
					}
				}
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(SecurityException e) 	{_AddError(e);}
			catch(Exception e) 			{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Validates a token only
		/// </summary>
		[WebMethod] public XmlDocument ValidateToken(string token) {
			try {
				userx.Validate(token);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Validates a user against a specific right
		/// </summary>
		[WebMethod] public XmlDocument Validate(string token, string right) {
			try {
				userx.Validate(token, right);
				_AddOk(userx.Users.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Gets user rights
		/// </summary>
		[WebMethod]
		public XmlDocument GetRights(string token) {
			try {
				userx.Validate(token);
				_AddOk(userx.Rights.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		#endregion

		#region Author (User) web service methods
		/// <summary>
		/// Register a new author in an existing blogspace
		/// </summary>
		[WebMethod] public XmlDocument RegisterAuthor(string username, string firstname, string surname, string email, string telno, string secret, string password, string password2, string spacename) {
			try {
				if (password != password2)
					throw(new x_exception("error_confirm", "password is not confirmed"));
				string defgroup = "author";
				userx.Add(username, firstname, surname, email, telno, secret, password, defgroup);
				blogspacex.AddUser(spacename, username, defgroup);
				userx.AddBlogspace(spacename, username, defgroup, true);
				Login(username, password);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Register a new subscriber (public profile) in an existing blogspace
		/// </summary>
		[WebMethod] public XmlDocument RegisterSubscriber(string username, string firstname, string surname, string email, string telno, string spacename, string extrainfo1, string extrainfo2, string extrainfo3, string extrainfo4) {
			try {
				string defgroup = "public";
				string defsecret = "umlungu";
				string defpassw = "password";
				userx.Add(username, firstname, surname, email, telno, defsecret, defpassw, defgroup, extrainfo1, extrainfo2, extrainfo3, extrainfo4);
				blogspacex.AddUser(spacename, username, defgroup);
				userx.AddBlogspace(spacename, username, defgroup, true);
				_AddOk(userx.User.OuterXml);
				//Login(username, defpassw);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument UpdateSubscriber(string token, string name, string firstname, string surname, string email, string telno, string extrainfo1, string extrainfo2, string extrainfo3, string extrainfo4) {
			try {
				string defgroup = "public";
				string defpassw = "password";
				userx.Validate(token, "User.Edit", name);
				userx.Update(name, firstname, surname, email, telno, defgroup, defpassw, extrainfo1, extrainfo2, extrainfo3, extrainfo4);
				_AddOk();
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument UploadNewsletter(string token, string subject, string message, string filename, string group) {
			try {
				userx.Validate(token, "Blogspace.SendNewsletter");
				AddOk();
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Users: Sends a newsletter (as an attatchement) to a user list defined by a group
		/// </summary>
		[WebMethod] public XmlDocument SendNewsletter(string token, string subject, string message, string filename, string group) {
			try {
				x_config config = new x_config();
				userx.Validate(token, "Blogspace.SendNewsletter");
				string filepath = Server.MapPath(String.Concat(config.EmailDocPath, filename));
				_AddOk(userx.SendEmail(group, subject, message, filepath).OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Users: Sends a blog formattted by an xsl template to a group of users within a blogspace
		/// </summary>
		[WebMethod] public XmlDocument SendNews(string token, string subject, string name, string topic, string id, string group, string xslfilename) {
			try {
				x_config config = new x_config();
				userx.Validate(token, "Blogspace.SendNewsletter");
				blogx.Get(name, topic, id);
				blogspacex.Get(name);
				string filepath = Server.MapPath(String.Concat(config.NewsXslPath, xslfilename));
				string logpath = Server.MapPath(config.NewsLogPath);
				_AddOk(userx.SendEmail(group, subject, name, topic, filepath, logpath, blogx, blogspacex).OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region Blogspace web service methods
		/// <summary>
		/// Space: Get a specific thoughtspace
		/// </summary>
		//[WebMethod] public XmlDocument GetSpace(string name) {
		[WebMethod] public XmlDocument GetSpace(string token, string name) {
			try {
				userx.Validate(token, "Blogspace.Get");
				blogspacex.Get(name);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument ListSpaces(string token) {
			try {
				userx.Validate(token, "Blogspace.List");
				blogspacex.List();
				_AddOk(blogspacex.Blogspaces.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddSpace(string token, string name, string type, string title, string text, string admin, string wanttopics) {
			try {
				userx.Validate(token, "Blogspace.Add");
				blogspacex.Add(name, type, title, text, admin, true, (wanttopics == "yes"));
				blogspacex.Get(name);
				userx.AddBlogspace(name, admin, "", false);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument EditSpace(string token, string name, string type, string title, string text, string wanttopics) {
			try {
				userx.Validate(token, "Blogspace.Edit");
				blogspacex.Update(name, type, title, text, (wanttopics == "yes"));
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument UpdateSpace(string token, string name, string type, string title, string text, string author, string image, string blogtitle, string bloghtml) {
			try {
				userx.Validate(token, "Blogspace.Edit");
				blogspacex.Update(name, type, title, text);
				author = (author == "" || author == null)? userx.Name : author;
				blogspacex.AddBlog(name, author, blogtitle, image, bloghtml);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument RemoveSpace(string token, string name) {
			try {
				userx.Validate(token, "Blogspace.Remove");
				blogspacex.Remove(name);
				userx.RemoveBlogspace(name);
				_AddOk(blogspacex.Blogspaces.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument GetSpaceBlog(string token, string name) {
			try {
				userx.Validate(token, "Blogspace.Get");
				blogspacex.GetBlog(name);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddSpaceBlog(string token, string name, string author, string title, string image, string html) {
			try {
				userx.Validate(token, "Blogspace.Edit");
				author = (author == "" || author == null)? userx.Name : author;
				blogspacex.AddBlog(name, author, title, image, html);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddSpaceImage(string token, string name, string filename) {
			try {
				userx.Validate(token, "Blogspace.AddImage");
				blogspacex.AddImage(name, filename);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument ChangeArchive(string token, string name, string type) {
			try {
				userx.Validate(token, "Blogspace.Archive");
				blogspacex.ChangeArchive(name, type);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: Remove a user from a blogspace
		/// </summary>
		[WebMethod] public XmlDocument DeleteUser(string token, string name, string user) {
			try {
				userx.Validate(token, "Blogspace.DeleteUser");
				blogspacex.DeleteUser(name, user);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: Remove a user, including all blogspaces
		/// </summary>
		[WebMethod] public XmlDocument RemoveUser(string token, string name) {
			try {
				userx.Validate(token, "User.Delete");
				userx.Get(name);
				foreach (XmlNode node in userx.User.SelectNodes("//blogspaces/blogspace")) {
					blogspacex.DeleteUser(((XmlElement)node).GetAttribute("name"), name);
				}
				userx.Delete(name);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddLink(string token, string name, string text, string url) {
			try {
				userx.Validate(token, "Blogspace.ManageLinks");
				blogspacex.AddLink(name, text, url);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument EditLink(string token, string name, string id, string text, string url) {
			try {
				userx.Validate(token, "Blogspace.ManageLinks");
				blogspacex.EditLink(name, Convert.ToInt32(id), text, url);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument DeleteLink(string token, string name, string id) {
			try {
				userx.Validate(token, "Blogspace.ManageLinks");
				blogspacex.DeleteLink(name, Convert.ToInt32(id));
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddTopic(string token, string name, string topic, string title, string type) {
			try {
				userx.Validate(token, "Blogspace.AddTopic");
				blogspacex.AddTopic(name, topic, title, type);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument EditTopic(string token, string name, string topic, string title, string type) {
			try {
				userx.Validate(token, "Blogspace.EditTopic");
				blogspacex.EditTopic(name, topic, title, type);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument DeleteTopic(string token, string name, string topic) {
			try {
				userx.Validate(token, "Blogspace.EditTopic");
				blogspacex.DeleteTopic(name, topic);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument GetTopicBlog(string token, string name, string topic) {
			try {
				userx.Validate(token, "Blogspace.Get");
				blogspacex.GetBlog(name, topic);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddTopicBlog(string token, string name, string topic, string author, string title, string image, string html) {
			try {
				userx.Validate(token, "Blogspace.EditTopic");
				author = (author == "" || author == null)? userx.Name : author;
				blogspacex.AddBlog(name, topic, author, title, image, html);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument AddTopicImage(string token, string name, string topic, string filename) {
			try {
				userx.Validate(token, "Blogspace.AddImage");
				blogspacex.AddImage(name, topic, filename);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument UpdateTopic(string token, string name, string topic, string label, string type, string author, string title, string image, string html) {
			try {
				userx.Validate(token, "Blogspace.EditTopic");
				blogspacex.EditTopic(name, topic, label, type);
				author = (author == "" || author == null)? userx.Name : author;
				blogspacex.AddBlog(name, topic, author, title, image, html);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Space: 
		/// </summary>
		[WebMethod] public XmlDocument GetSpaceCurrent(string token, string name) {
			try {
				userx.Validate(token, "Blogspace.Get");
				blogspacex.Current(name);
				_AddOk(blogspacex.Blogspace.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region Blog web service methods
		/// <summary>
		/// Blog: Get a Specific blog
		/// </summary>
		[WebMethod] public XmlDocument GetBlog(string token, string name, string topic, string archive, string id) {
			try {
				userx.Validate(token, "Blog.Get");
				topic = (topic == "")? "default" : topic;
				if (archive == "" || archive == "current" || archive == "0")
					blogx.Get(name, topic, id);
				else
					blogx.Get(name, topic, archive, id);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: List blogs in a space/topic/archive
		///		- revised version that allows multiple topics to be listed or 'all' (with exclusions)
		/// </summary>
		[WebMethod] public XmlDocument ListBlogs(string token, string name, string topicList, string archive) {
			try {
				userx.Validate(token, "Blog.List");
				x_nixlist topics = new x_nixlist(topicList);
				bool noArchive = (archive == "" || archive == "current" || archive == "0");
				if (noArchive) {
					blogx.List(name, "default");	// start with default
					blogx.BlogList.ParentNode.RemoveChild(blogx.BlogList);
					x_blog thisblog = new x_blog(Application);
					foreach(XmlNode topic in blogx.Blogs.SelectNodes("//topics/topic")) {
						XmlElement topicel = (XmlElement) topic;
						string topicname = topicel.GetAttribute("name");
						if (topics.IsIn(topicname)) {
							thisblog.List(name, topicname);
							blogx.Blogs.AppendChild(blogx.Document.ImportNode(thisblog.BlogList, true));
						}
					}
				} else {
					blogx.List(name, "default", archive);	// need at least one?
					// need to use nixlist as above...
				}
				_AddOk(blogx.Blogs.InnerXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: List blogs in a space/topic/archive
		/// 	- original version that only lists a single topic or all
		/// </summary>
		[WebMethod] public XmlDocument ListBlogsOrg(string token, string name, string topic, string archive) {
			try {
				userx.Validate(token, "Blog.List");
				bool wantall = (topic == "all" || topic == "0");
				topic = (topic == "" || wantall)? "default" : topic;
				if (archive == "" || archive == "current" || archive == "0") {
					blogx.List(name, topic);
					if (wantall) {	// get all current blogs
						blogspacex.Current(name);
						XmlNode currnode = blogspacex.Blogspace.SelectSingleNode("//blogs/current");
						blogx.Blogs.SelectSingleNode("//blogs").InnerXml = (currnode != null)? currnode.InnerXml : "";
						blogx.Blogs.SelectSingleNode("//archives").InnerXml = "";	// archive list only when topic selected
					}
				}
				else
					blogx.List(name, topic, archive);
				_AddOk(blogx.Blogs.InnerXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument AddBlog(string token, string name, string topic, string title, string xml) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "") ? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, xml);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument AddBlogID(string token, string name, string topic, string id, string title, string xml) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "") ? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, xml);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddTextBlog(string token, string name, string topic, string title, string text) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "")? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, text, false);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddTextBlogID(string token, string name, string topic, string id, string title, string text) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "")? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, text, false);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddHtmlBlog(string token, string name, string topic, string title, string html) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "")? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, html, true);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument AddHtmlBlogXml(string token, string name, string topic, string title, string html, string xml) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "") ? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, html, true, xml);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddHtmlBlogID(string token, string name, string topic, string id, string title, string html) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "")? "default" : topic;
				blogx.Add(name, topic, userx.Name, title, id, html, true);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddHtmlBlogDate(string token, string name, string topic, string year, string month, string day, string title, string text, string html) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "")? "default" : topic;
				blogx.Add(name, topic, userx.Name, year, month, day, null, title, text, html, true);	// null = id, add id to method?
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		[WebMethod]
		public XmlDocument AddImageBlog(string token, string name, string topic, string title, string text, string image) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "") ? "default" : topic;
				blogx.AddImage(name, topic, userx.Name, title, text, false, image);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument AddImageBlogID(string token, string name, string topic, string id, string title, string text, string image) {
			try {
				userx.Validate(token, "Blog.Add");
				topic = (topic == "") ? "default" : topic;
				blogx.AddImage(name, topic, userx.Name, title, id, text, false, image);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument DeleteBlog(string token, string name, string topic, string id) {
			try {
				userx.Validate(token, "Blog.Delete");
				topic = (topic == "")? "default" : topic;
				blogx.Delete(name, topic, id);
				_AddOk();
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument EditBlog(string token, string name, string topic, string id, string title, string xml) {
			try {
				userx.Validate(token, "Blog.Edit");
				topic = (topic == "")? "default" : topic;
				blogx.Update(name, topic, id, title, xml);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument EditTextBlog(string token, string name, string topic, string id, string title, string text) {
			try {
				userx.Validate(token, "Blog.Edit");
				topic = (topic == "")? "default" : topic;
				blogx.Update(name, topic, id, title, text, false);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument EditHtmlBlog(string token, string name, string topic, string id, string title, string html) {
			try {
				userx.Validate(token, "Blog.Edit");
				topic = (topic == "")? "default" : topic;
				blogx.Update(name, topic, id, title, html, true);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: Updates a blog that has a title + html + other xml fields
		/// </summary>
		[WebMethod(Description="Updates a blog that has a title + html + other xml fields")]
		public XmlDocument EditHtmlBlogXml(string token, string name, string topic, string id, string title, string html, string xml) {
			try {
				userx.Validate(token, "Blog.Edit");
				topic = (topic == "") ? "default" : topic;
				blogx.Update(name, topic, id, title, html, true, xml);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument EditHtmlBlogDate(string token, string name, string topic, string id, string title, string text, string html) {
			try {
				userx.Validate(token, "Blog.Edit");
				topic = (topic == "")? "default" : topic;
				blogx.Update(name, topic, id, title, text, html);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region Blog-Comment web service methods
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument GetBlogComment(string token, string name, string topic, string id, string cid) {
			try {
				userx.Validate(token, "Comment.View");
				topic = (topic == "")? "default" : topic;
				blogx.Get(name, topic, id);
				XmlNode comment = blogx.Blog.SelectSingleNode("comments/comment[@id='"+cid+"']");
				if (comment != null)
					_AddOk(comment.OuterXml);
				else
					throw(new x_exception("error_commentexist", "comment does not exist"));
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument AddBlogComment(string token, string name, string topic, string id, string author, string title, string text) {
			try {
				userx.Validate(token, "Comment.Add");
				if (author == "" || author == "null") {	// default to author from token user
					userx.Validate(token);	// since validation for 'public' rights don't load user
					author = userx.Name;
				}
				topic = (topic == "")? "default" : topic;
				blogx.AddComment(name, topic, Convert.ToInt32(id), userx.Username, author, title, text, true);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument EditBlogComment(string token, string name, string topic, string id, string cid, string title, string text) {
			try {
				userx.Validate(token, "Comment.Edit");
				topic = (topic == "")? "default" : topic;
				blogx.EditComment(name, topic, Convert.ToInt32(id), Convert.ToInt32(cid), title, text);
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod] public XmlDocument DeleteBlogComment(string token, string name, string topic, string id, string cid) {
			try {
				userx.Validate(token, "Comment.Delete");
				topic = (topic == "")? "default" : topic;
				blogx.DeleteComment(name, topic, Convert.ToInt32(id), Convert.ToInt32(cid));
				_AddOk(blogx.Blog.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region Blog-Image web service methods
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument GetBlogImage(string token, string name, string topic, string id, string iid) {
			try {
				userx.Validate(token, "Image.View");
				topic = (topic == "") ? "default" : topic;
				blogx.Get(name, topic, id);
				XmlNode image = blogx.Blog.SelectSingleNode("images/image[@id='" + iid + "']");
				if (image != null)
					_AddOk(image.OuterXml);
				else
					throw (new x_exception("error_imageexist", "image does not exist"));
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument AddBlogImage(string token, string name, string topic, string id, string author, string title, string text) {
			try {
				userx.Validate(token, "Image.Add");
				if (author == "" || author == "null") {	// default to author from token user
					userx.Validate(token);	// since validation for 'public' rights don't load user
					author = userx.Name;
				}
				topic = (topic == "") ? "default" : topic;
				blogx.AddImage(name, topic, Convert.ToInt32(id), userx.Username, author, title, text, true);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument EditBlogImage(string token, string name, string topic, string id, string iid, string title, string text) {
			try {
				userx.Validate(token, "Image.Edit");
				topic = (topic == "") ? "default" : topic;
				blogx.EditImage(name, topic, Convert.ToInt32(id), Convert.ToInt32(iid), title, text);
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// Blog: 
		/// </summary>
		[WebMethod]
		public XmlDocument DeleteBlogImage(string token, string name, string topic, string id, string iid) {
			try {
				userx.Validate(token, "Image.Delete");
				topic = (topic == "") ? "default" : topic;
				blogx.DeleteImage(name, topic, Convert.ToInt32(id), Convert.ToInt32(iid));
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod]
		public XmlDocument DefaultBlogImage(string token, string name, string topic, string id, string iid) {
			try {
				userx.Validate(token, "Image.Edit", name);
				topic = (topic == "") ? "default" : topic;
				blogx.DefaultImage(name, topic, Convert.ToInt32(id), Convert.ToInt32(iid));
				_AddOk(blogx.Blog.OuterXml);
			} catch (x_exception e) { _AddError(e); } catch (System.Exception e) { _AddError(e); }
			return (Result);
		}
		#endregion

		#region User web service methods
		/// <summary>
		/// User: List all users
		/// </summary>
		[WebMethod] public XmlDocument ListUsers(string token) {
			try {
				userx.Validate(token, "User.List");
				_AddOk(userx.List().OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: List all users
		/// </summary>
		[WebMethod] public XmlDocument ListUsersByGroup(string token, string group) {
			try {
				userx.Validate(token, "User.List");
				_AddOk(userx.List(group).OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument GetUser(string token, string name) {
			try {
				userx.Validate(token, "User.Get", name);
				userx.Get(name);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: Adds a new user
		/// </summary>
		[WebMethod] public XmlDocument AddUser(string token, string name, string firstname, string surname, string email, string telno, string secret, string password, string group) {
			try {
				userx.Validate(token, "User.Register");
				userx.Add(name, firstname, surname, email, telno, secret, password, group);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument EditUser(string token, string name, string firstname, string surname, string email, string telno, string group) {
			try {
				userx.Validate(token, "User.Edit", name);
				userx.Update(name, firstname, surname, email, telno, group);
				_AddOk();
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: Change login details
		/// </summary>
		[WebMethod] public XmlDocument ChangeLogin(string token, string name, string password, string secret) {
			try {
				userx.Validate(token, "User.ChangePassword", name);
				userx.ChangeLogin(name, password, secret);
				_AddOk();
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);		
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument AddUserBlog(string token, string name, string title, string html) {
			try {
				userx.Validate(token, "User.Edit", name);
				name = (name == "" || name == null)? userx.Username : name;
				userx.AddBlog(name, userx.Name, title, html);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument GetUserBlog(string token, string name) {
			try {
				userx.Validate(token, "User.Get", name);
				userx.GetBlog(name);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region User-Space web service methods
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument GetUserSpaces(string token, string name) {
			try {
				userx.Validate(token, "User.Get", name);
				userx.Get(name);
				
				XmlElement spacesel = (XmlElement) userx.User.SelectSingleNode("//blogspaces");
				XmlNodeList spaces = spacesel.SelectNodes("blogspace");
				foreach (XmlNode space in spaces) {
					XmlElement spaceel = (XmlElement) space;
					blogspacex.Get(spaceel.GetAttribute("name"));
					space.InnerText = blogspacex.Blogspace.SelectSingleNode("/blogspace/title").InnerText;
					XmlElement thisspaceel = (XmlElement) blogspacex.Blogspace.SelectSingleNode("/blogspace");
					spaceel.SetAttribute("type", (thisspaceel != null)? thisspaceel.GetAttribute("type") : "text");
				}
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument AddUserSpace(string token, string name, string spacename) {
			try {
				userx.Validate(token, "User.AddBlogspace", name);
				blogspacex.AddUser(spacename, name);
				userx.AddBlogspace(spacename, name, "", false);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument DeleteUserSpace(string token, string name, string spacename) {
			try {
				userx.Validate(token, "User.RemoveBlogspace", name);
				blogspacex.DeleteUser(spacename, name);
				userx.RemoveBlogspace(spacename, name);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// User: 
		/// </summary>
		[WebMethod] public XmlDocument DefaultUserSpace(string token, string name, string spacename) {
			try {
				userx.Validate(token, "User.AddBlogspace", name);
				userx.DefaultBlogspace(spacename, name);
				_AddOk(userx.User.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion

		#region Recruit web service methods
		/// <summary>
		/// Add a potential subscriber to the Recruit list. 
		///	- A recruit will receive an email and need to confirm subscription before being added as a subscriber
		/// </summary>
		[WebMethod] public XmlDocument AddRecruit(string spacename, string firstname, string surname, string email) {
			try {
				recruitx.Add(spacename, email, firstname, surname);
				recruitx.SendConfirmation(spacename);
				_AddOk(recruitx.Recruit.OuterXml);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		/// <summary>
		/// Add a potential subscriber to the Recruit list. 
		///	- A recruit will receive an email and need to confirm subscription before being added as a subscriber
		/// </summary>
		[WebMethod] public XmlDocument RegisterRecruit(string id, string telno, string extrainfo1, string extrainfo2, string extrainfo3, string extrainfo4) {
			try {
				string defgroup = "public";
				string defsecret = "umlungu";
				string defpassw = "password";
				recruitx.Get(id);
				string username = recruitx.Email;
				if (userx.Is(username))
					userx.Update(username, recruitx.FirstName, recruitx.Surname, recruitx.Email, telno, defgroup, defpassw, extrainfo1, extrainfo2, extrainfo3, extrainfo4);
				else
					userx.Add(username, recruitx.FirstName, recruitx.Surname, recruitx.Email, telno, defsecret, defpassw, defgroup, extrainfo1, extrainfo2, extrainfo3, extrainfo4);
				blogspacex.AddUser(recruitx.Blogspace, username, defgroup);
				userx.AddBlogspace(recruitx.Blogspace, username, defgroup, true);
				_AddOk(userx.User.OuterXml);
				//Login(username, defpassw);
			} 
			catch(x_exception e)		{_AddError(e);}
			catch(System.Exception e) 	{_AddError(e);}
			return(Result);
		}
		#endregion
	}
}
